#ifndef __CORE_VECTOR3__
#define __CORE_VECTOR3__

namespace Core
{
	class rtVector2;
	class rtAngles;
	class rtMatrix3;
	class rtVector3
	{
	public:	
		float			x;
		float			y;
		float			z;

		rtVector3(void);
		explicit rtVector3(const float x, const float y, const float z);
		static rtVector3 vec3_origin;
		static rtVector3 vec3_zero;
		void 			set(const float x, const float y, const float z);
		void			zero(void);

		float			operator [] (const int index) const;
		float&			operator [] (const int index);
		rtVector3		operator - () const;
		rtVector3&		operator = (const rtVector3& a);
		float			operator * (const rtVector3& a) const;
		rtVector3		operator * (const float a) const;
		rtVector3		operator / (const float a) const;
		rtVector3		operator + (const rtVector3& a) const;
		rtVector3		operator - (const rtVector3& a) const;
		rtVector3&		operator += (const rtVector3& a);
		rtVector3&		operator -= (const rtVector3& a);
		rtVector3&		operator /= (const rtVector3& a);
		rtVector3&		operator /= (const float a);
		rtVector3&		operator *= (const float a);

		friend rtVector3	operator * ( const float a, const rtVector3 b );

		bool			compare(const rtVector3& a) const;
		bool			compare(const rtVector3& a, const float epsilon) const;
		bool			operator == (const rtVector3& a) const;
		bool			operator != (const rtVector3& a) const;

		bool			fixDegenerateNormal(void);
		bool			fixDenormals(void);

		rtVector3		cross(const rtVector3& a) const;
		rtVector3&		cross(const rtVector3& a, const rtVector3& b);
		float			length(void) const;
		float			lengthSqr(void) const;
		float			lengthFast(void) const;
		float			normalize(void);
		float			normalizeFast(void);
		rtVector3&		truncate(float length);
		void			clamp(const rtVector3& min, const rtVector3& max);
		void			snap(void);
		void			snapInt(void);

		int				getDimension(void) const;

		float			toYaw(void) const;
		float			toPitch(void) const;
		rtAngles		toAngles(void) const;
		rtMatrix3		toMat3(void) const;
		const rtVector2& toVec2(void) const;
		rtVector2&		toVec2(void);
		const float*	toFloatPtr(void) const;
		float*			toFloatPtr(void);

		void			normalVectors(rtVector3& left, rtVector3& down) const;
		void			orthogonalBasis(rtVector3& left, rtVector3& up) const;

		void			projectOntoPlane(const rtVector3& normal, const float overBounce = 1.0f);

		bool			projectAlongPlane(const rtVector3& normal, const float epsilon, const float overBounce = 1.0f);
		void			projectSelfOntoSphere(const float radius);

		void			lerp(const rtVector3& v1, const rtVector3& v2, const float l);
		void			slerp(const rtVector3& v1, const rtVector3& v2, const float l);
	};
}

#endif


